#!/usr/bin/env python
# -*- coding: utf-8 -*-
#### Copyright (c) 2008 Clóvis Fabrício Costa - All rights reserved

import os
import shutil

class Wrapper(object):
    def __init__(self, cmd):
        self._cmd = cmd
        
    def do_stuff(self, *args, **kwds):
        return args, kwds
    
    def __call__(self, *args, **kwds):
        args, kwds = self.do_stuff(*args, **kwds)
        return self._cmd(*args, **kwds)


class StrArgsWrapper(Wrapper):
    def do_stuff(self, *args, **kwds):
        args = [str(arg) for arg in args]
        for key in kwds:
            kwds[key] = str(kwds[key])
        return args, kwds
    
    
class Commands(object):
    _pysh_external = {
            os: [
                'chdir', 'access', 'chflags', 'chroot', 'chmod', 'chown', 
                'lchflags','lchmod', 'lchown', 'link', 'listdir', 'lstat', 
                'mkfifo', 'mknod', 'mkdir', 'makedirs', 'pathconf', 
                'readlink', 'remove', 'removedirs', 'renames', 'rmdir',
                'stat', 'statvfs', 'symlink', 'unlink', 'utime', 'walk',
                'startfile',
            ],
            os.path: [
                'basename', 'dirname', 'exists', 'lexists', 'expandvars',
                'getatime', 'getmtime', 'getctime', 'getsize', 'isabs', 
                'isfile', 'isdir', 'islink', 'ismount', 'relpath',
            ],
            shutil: [
                'copy', 'copy2', 'copystat', 'copymode', 'copyfile', 
                'copytree', 'rmtree', 'move',
            ],
            
        }

    _pysh_aliases = {
            'cd': 'chdir',
            'md': 'makedirs',
            'rm': 'remove',
            'rename': 'renames',
            'start': 'startfile',
            'mv': 'move',
        }

    _pysh_default_wrapper = StrArgsWrapper
    
    _pysh_wrappers = {
        }

    def __getattr__(self, attr):
        if attr.startswith('_pysh_'):
            return super(Commands, self).__getattr__(self, attr)
        else:
            attr = self._pysh_aliases.get(attr, attr)
            for namespace, command_names in self._pysh_external.iteritems():
                if attr in command_names:
                    cmd = getattr(namespace, attr)
                    break
            else:
                print 'DEBUG: not found', attr
                return super(Commands, self).__getattr__(self, attr)
            for wrapper, command_names in self._pysh_wrappers.iteritems():
                if attr in command_names:
                    cmd = wrapper(cmd)
            else:
                cmd = self._pysh_default_wrapper(cmd)
            return cmd

    def cp(self, src, dst):
        src = str(src)
        dst = str(dst)
        try:
            return shutil.copytree(src, dst)
        except OSError:
            return shutil.copy2(src, dst)
    
    def open(self, path, *args, **kwds):
        path = str(path)
        return open(path, *args, **kwds)

c = Commands()